package com.the_last.service.impl;

import com.the_last.constant.RedisKeyConstant;
import com.the_last.pojo.bo.LoginUser;
import com.the_last.pojo.dto.LoginDTO;
import com.the_last.pojo.vo.LoginVO;
import com.the_last.service.IAuthService;
import com.the_last.utils.JwtUtil;
import com.the_last.utils.RedisUtil;
import com.the_last.utils.Result;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements IAuthService {
    
    private final AuthenticationManager authenticationManager;
    
    @Resource
    private final RedisUtil redisUtil;
    
    @Override
    public Result<LoginVO> login(LoginDTO loginDTO) {
        log.info("用户登录请求: {}", loginDTO.getUserName());
        
        try {
            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(loginDTO.getUserName(), loginDTO.getPassword());
            
            Authentication authenticate = authenticationManager.authenticate(authenticationToken);
            
            if (authenticate == null) {
                log.warn("用户认证失败: {}", loginDTO.getUserName());
                return Result.fail("用户名或密码错误", 401);
            }
            
            LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
            Long userId = loginUser.getUser().getId();  // 内部使用，不暴露
            String userName = loginUser.getUser().getUserName();
            
            Map<String, Object> claims = new HashMap<>();
            claims.put("userId", userId);
            
            String token = JwtUtil.sign(claims);
            
            if (token == null) {
                log.error("生成JWT令牌失败: {}", userName);
                return Result.fail("系统错误，请稍后重试");
            }
            String redisKey = RedisKeyConstant.LOGIN_KEY + userId;
            String redisPermVersionKey = RedisKeyConstant.USER_PERM_VERSION_KEY + userId;
            redisUtil.set(redisKey, loginUser, 72 * RedisUtil.ONE_HOUR);
            redisUtil.set(redisPermVersionKey, loginUser.getUser().getPermVersion(), 72 * RedisUtil.ONE_HOUR);
            List<String> permissionList = loginUser.getAuthorityList();
            
            LoginVO loginVO = LoginVO.builder()
                    .token(token)
                    .userName(userName)
                    .phone(loginUser.getUser().getPhone())
                    .permissionList(permissionList)
                    .build();
            
            log.info("用户登录成功: {}, 权限数量: {}", userName, permissionList.size());
            return Result.success(loginVO);
            
        } catch (AuthenticationException e) {
            log.warn("用户认证失败: {}, 原因: {}", loginDTO.getUserName(), e.getMessage());
            return Result.fail("用户名或密码错误", 401);
        } catch (Exception e) {
            log.error("登录过程发生异常: {}", loginDTO.getUserName(), e);
            return Result.fail("系统错误，请稍后重试");
        }
    }
    
    @Override
    public Result<Void> logout(LoginUser loginUser) {
        try {
            if (loginUser != null && loginUser.getUser() != null) {
                long userId = loginUser.getUser().getId();
                
                // 使用与登录时一致的key结构
                String redisKey = RedisKeyConstant.LOGIN_KEY + userId;
                redisUtil.delete(redisKey);
                
                log.info("用户退出登录成功: userId={}", userId);
            }
            
            return Result.success();
        } catch (Exception e) {
            log.error("退出登录过程发生异常", e);
            return Result.fail("退出登录失败");
        }
    }
}